package com.AUI.components
{
	import com.AUI.*;
	import com.AUI.events.*;
	
	import flash.display.*;
	import flash.events.*;
	/**
	 * @eventType com.AUI.events.AListEvent#ITEM_CLICK
	 */
	[Event(name="itemClick", type="com.AUI.events.AItemEvent")]
	/**
	 * List.
	 * Its all items are AButton instance.
	 * <p>In the single selection mode,the items are AGroupButton,In multiple selection mode,the items are AToggleButton.</p>
	 * @author HuangMinPing
	 * @site www.AminLab.com
	 */
	public class List extends V
	{
		/**
		 * Multiple selection flag.
		 */
		private var _multipleSelection:Boolean = false;
		/**
		 * Group number of the items if _multipleSelection is false.
		 */
		private var _number:uint;
		/**
		 * Max item width.
		 */
		private var _maxItemWidth:int;
		/**
		 * Constructor.
		 * @param multipleSelection Indicates whether the list can be multiple selection.
		 */
		public function List(multipleSelection:Boolean = false)
		{
			// init attributes
			_multipleSelection = multipleSelection;
			_number = int(_multipleSelection) || AUIPrivate.incGUN();
			
			/**************** INITCOMPLETE ****************/
			Object(this).constructor == List && initComplete();
		}
		/**
		 * @private
		 */
		override protected function initComplete():void
		{
			super.initComplete();
			verticalScrollBar = new VScrollBar;
		}
		/**
		 * The number of items in this component.
		 */
		public function get numItems():int
		{
			return this.numElements;
		}
		/**
		 * Removes a item(AButton) from List by name.
		 * @param name Option name.
		 * @return The item that was removed.
		 */
		public function removeItem(name:String):Button
		{
			return removeItemAt(this.getItemIndex(name));
		}
		/**
		 * Removes a item(AButton) at the specified index from List.
		 * @param name Option name.
		 * @return The item that was removed.
		 */
		public function removeItemAt(index:int):Button
		{
			return Button(removeElementAt(index));
		}
		/**
		 * Replaces the item(AButton) at the specified index location with another item.
		 * @param name Option name.
		 * @param index The index position of the item to be replaced.
		 * @return The item that was replaced.
		 */
		public function replaceItemAt(name:String,index:int):Button
		{
			var oldOption:Button = Button(elements.removeChildAt(index));
			var newOption:Button = addItemAt(name,index);
			newOption.checked = oldOption.checked;
			updateContentBox();
			return oldOption;
		}
		/**
		 * Retrieves the name of the item(AButton) at the specified index.
		 * @param index The index position of the item to be retrieved.
		 */
		public function getItemAt(index:int):String
		{
			return AComponent(getElementAt(index)).value;
		}
		/**
		 * Retrieves the index of the item(AButton) by name.
		 * @param index The index position of the item to be retrieved.
		 */
		public function getItemIndex(name:String):int
		{
			var item:Button;
			for(var i:int = 0,len:int = numElements;i < len;++i)
			{
				item = Button(this.getElementAt(i));
				if(item.value == name)
				{
					return i;
				}
			}
			return -1;
		}
		/**
		 * Appends a item(AButton) to the end of the List.
		 * @param name Option name.
		 * @return The item that was added.
		 */
		public function addItem(name:String):Button
		{
			return addItemAt(name,numElements);
		}
		/**
		 * Inserts a item(AButton) into the list at the specified index location.
		 * @param name Option name.
		 * @param index The index at which to add the item.
		 * @return The item to be added to the list.
		 */
		public function addItemAt(name:String,index:int):Button
		{
			AUIPrivate.addPreSelectorNames(this.ename +' > item');
			var item:Button = _multipleSelection ? new ToggleButton(name) : new GroupButton(_number,name);
			var itemWidth:int = item.width;
			// check width
			if(isAutoWidth() == true)
			{
				if(itemWidth > _maxItemWidth)
				{
					_maxItemWidth = itemWidth;
					setElements('width',_maxItemWidth);
				}
				else
				{
					item.width = _maxItemWidth;
				}  
			}
			else
			{
				item.width = boxModel.content.width;
			}
			// done
			super.addElementAt(item,index);
			return item;
		}
		/**
		 * Get or set a string array that indicates the name of items of the List.
		 */
		override public function set value(variable:*):void
		{
			var items:Array = variable is String ? variable.split(',') : (variable as Array);
			var cur:int = numElements;
			var end:int = items ? items.length : 0;
			// append item
			while(cur < end)
			{
				AUIPrivate.addPreSelectorNames(this.ename +' > item');
				elements.addChild(_multipleSelection ? new ToggleButton : new GroupButton(_number));
				++cur;
			}
			// delete item
			while(cur > end)
			{
				elements.removeChildAt(0);
				--cur;
			}
			// update item's value
			for(var i:int = 0;i < end;++i)
			{
				var item:AComponent = AComponent(getElementAt(i));
				item.value = items[i];
			}
			// update item's width
			if(isAutoWidth() == true)
			{
				var itemWidth:int
				var itemJ:DisplayObject;
				for(var j:int = 0,lenJ:int = numElements;j < lenJ;++j)
				{
					itemJ = getElementAt(j);
					itemWidth = itemJ.width;
					if(itemWidth > _maxItemWidth)
					{
						_maxItemWidth = itemWidth;
					}
				}
				setElements('width',_maxItemWidth);
			}
			else
			{
				setElements('width',boxModel.content.width);
			}
			// update
			updateAlignment();
			updateContentBox();
		}
		override public function get value():*
		{
			var len:int = numElements;
			var items:Array = new Array(len);
			for(var i:int = 0;i < len;++i)
			{
				items[i] = AComponent(getElementAt(i)).value;
			}
			return items;
		}
		/**
		 * Get or set a integer array that representing the currently selected indices.The value "null" be gotten or set is indicates nothing selected.
		 * <p>In single selection mode,the return array length is always 1 when be gotten,and it use first value of the given array when be set.</p>
		 * <p>Note: You can use getElementAt function to get the selected items.</p>
		 */
		public function set selectedIndices(value:Array):void
		{
			var indices:Array = value || new Array;
			var i:int;
			var lenE:int;
			var lenI:int;
			var button:Button;
			// 1.set all items' selected to false
			for(i = 0,lenE = numElements;i < lenE;++i)
			{
				button = Button(getElementAt(i));
				button.checked = false;
			}
			// 2.set dest items' selected to true;
			for(i = 0,lenI = indices.length;i < lenI;++i)
			{
				var index:uint = indices[i];
				if(index >= lenE)
				{
					continue;
				}
				button = Button(getElementAt(index));
				button.checked = true;
			}
		}
		public function get selectedIndices():Array
		{
			var indices:Array = new Array;
			for(var i:int = 0,len:int = numElements;i < len;++ i)
			{
				var button:Button = Button(getElementAt(i));
				if(button.checked)
				{
					indices.push(i);
				}
			}
			return indices.length ? indices : null;
		}
		/**
		 * Get or set a integer array that representing the currently selected indices.The value "null" be gotten or set is indicates nothing selected.
		 * <p>In single selection mode,the return array length is always 1 when be gotten,and it use first value of the given array when be set.</p>
		 * <p>Note: You can use getElementAt function to get the selected items.</p>
		 */
		public function set selectedIndex(value:int):void
		{
			selectedIndices = [value];
		}
		public function get selectedIndex():int
		{
			var index:int = -1;
			for(var i:int = 0,len:int = numElements;i < len;++ i)
			{
				var button:Button = Button(getElementAt(i));
				if(button.checked)
				{
					index = i;
					break;
				}
			}
			return index;
		}
		/**
		 * @private
		 */
		override protected function resizeBoxModel():void
		{
			if(isAutoWidth() == true)
			{
				if(boxModel.content.width != _maxItemWidth)
				{
					setElements('width',_maxItemWidth);
				}
			}
			else
			{
				if(drawStyle.content.width.value != elements.width)
				{
					setElements('width',drawStyle.content.width.value);
				}
			}
			super.resizeBoxModel();
		}
	}
}